use std::{
    env,
    fs::{self, File, OpenOptions},
    io::{BufRead, BufReader, Write},
};

use crate::account_item::AccountItem;
use crate::common::*;

#[derive(Debug)]
pub struct AccountBook {
    file: File,
    pub items: Vec<AccountItem>,
}

impl AccountBook {
    pub fn load_from_file() -> Self {
        let user_name = env::var("username").unwrap();
        println!("username: {}", user_name);
        let file_path = format!("C:\\Users\\{}\\{}", user_name, FILE_NAME);
        println!("file_path: {}", file_path);

        let file_path = file_path.as_str();
        let mut items: Vec<AccountItem> = vec![];
        let file_result = OpenOptions::new()
            .read(true)
            // .write(true)
            .create(true)
            .append(true)
            .open(file_path);
        // 打开文件失败
        if let Err(_) = file_result {
            // 文件不存在
            if let Err(_) = fs::metadata(file_path) {
                // 如果路径不存在，创建文件会失败
                let file = File::create(file_path).expect("创建文件失败");
                return AccountBook { file, items };
            } else {
                panic!("打开文件失败")
            }
        }
        let file = file_result.unwrap();
        let reader = BufReader::new(&file);
        for line in reader.lines() {
            let line = line.unwrap();
            let words: Vec<&str> = line.split(",;,").collect();
            if words.len() != 3 {
                panic!("文件损毁，请删除用户目录下的AccountBook.txt文件后重试！")
            }
            let account_item = AccountItem::new(
                words[0].to_string(),
                words[1].parse().expect("转换异常"),
                words[2].to_string(),
            );
            items.push(account_item);
        }
        AccountBook { file, items }
    }

    pub fn do_account(&mut self, item: AccountItem) {
        let write_line = format!("{},;,{},;,{}\n", &item.item_type, item.amount, &item.detail);
        let print_line = format!("{} {} {}", &item.item_type, item.amount, &item.detail);
        let write_result = self.file.write(write_line.as_bytes());
        if let Err(e) = write_result {
            println!("记账失败: {}", e);
            return;
        }
        self.items.push(item);
        println!("记账成功：{}", print_line);
    }
}

#[cfg(test)]
mod test {
    use crate::{account_item::AccountItem, common::INCOME};

    use super::AccountBook;

    #[test]
    fn load_from_file_test() {
        let account_book = AccountBook::load_from_file();
        println!("{:?}", account_book);
    }

    #[test]
    fn do_account_test() {
        let mut account_book = AccountBook::load_from_file();
        println!("{:?}", account_book);

        let account_item = AccountItem::new(INCOME.to_string(), 10, "测试".to_string());
        println!("{:?}", account_item);

        account_book.do_account(account_item);
        println!("{:?}", account_book);
    }
}
